package httpHandler

import (
	"encoding/json"
	baseHttp "gitee.com/zaiqiang231/go-base-app/base_app/http"
	sessionHandler "gitee.com/zaiqiang231/go-base-session/app/http/handler"
	"gitee.com/zaiqiang231/zcamp-service-camp/app/http/service"
	"gitee.com/zaiqiang231/zcamp-service-camp/app/model"
	"gitee.com/zaiqiang231/zcamp-service-camp/app/model/req"
	remoteRpc "gitee.com/zaiqiang231/zcamp-service-camp/app/rpc/remote"
	"gitee.com/zaiqiang231/zcamp-service-camp/app/util"
	userProto "gitee.com/zaiqiang231/zcamp-service-user/app/rpc/proto"
	"github.com/gin-gonic/gin"
	"github.com/gin-gonic/gin/binding"
	"net/http"
	"reflect"
	"strconv"
	"strings"
	"time"
)

func MyCampingData(c *gin.Context) {
	data, err := service.ServicePostInstance.MyCampingData()
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", data)
}

func CreatePost(c *gin.Context) {
	uid := c.GetInt64(KEY_AUTH_UID)
	var request req.PostCreateReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	uniqueId, tmperr := util.GetPostUniqueId(c, uint64(uid))
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}

	request.PostID = uniqueId
	request.Uid = uid
	request.PublishTime = time.Now()

	result, tmperr := json.Marshal(request.ReqImages)
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}
	request.Pictures = string(result)

	if len(request.ReqTopicNames) > 0 {
		request.TopicNames = strings.Join(request.ReqTopicNames, ",")
	}

	err := service.ServicePostInstance.PostCreate(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func UpdatePost(c *gin.Context) {
	var target map[string]interface{}
	if err := c.ShouldBindBodyWith(&target, binding.JSON); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	result, tmperr := json.Marshal(target["req_images"])
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}
	target["pictures"] = string(result)

	var request req.PostUpdateReq
	elem := reflect.TypeOf(&request).Elem() //通过反射获取type定义
	for i := 0; i < elem.NumField(); i++ {
		if elem.Field(i).Tag.Get("gorm") == "-" && len(elem.Field(i).Tag.Get("json")) > 0 {
			delete(target, elem.Field(i).Tag.Get("json"))
		}
	}

	err := service.ServicePostInstance.PostUpdateForMap(target)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func DelPost(c *gin.Context) {
	var request req.PostDelReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	atom := sessionHandler.GetAtom(c)
	err := service.ServicePostInstance.DeletePost(request.PostId, strconv.FormatInt(atom.Uid, 10))
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func DeletePostList(c *gin.Context) {
	var request req.IdsStringReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	err := service.ServicePostInstance.DeletePostList(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func GetPostList(c *gin.Context) {
	var request req.PostListReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, total, err := service.ServicePostInstance.GetPostList(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"total":    total,
		"page":     request.Page,
		"pageSize": request.PageSize,
	})
}

func PostOperate(c *gin.Context) {
	var request req.OperatePostReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	atom := sessionHandler.GetAtom(c)
	err := service.ServicePostInstance.PostOperate(atom.Uid, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}

	baseHttp.WriteResponse(c, 0, "success", nil)
}

func PostDetail(c *gin.Context) {
	var request req.PostDetailReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	postInfo, err := service.ServicePostInstance.GetPostDetail(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	count, _ := service.ServiceCommentInstance.GetCommentCount(strconv.FormatUint(postInfo.PostID, 10))

	uid, err := strconv.ParseInt(request.CreateUid, 10, 64)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	userResponse, err := remoteRpc.GetUserRpc().UserRpcServiceClient.GetUserInfo(c, &userProto.UserInfoRequest{
		Uid: uid,
	})
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	var campInfo *model.BaseCampInfo
	if postInfo.CampId != 0 {
		campInfo, err = service.ServiceCampInstance.GetBaseCampInfo(postInfo.CampId)
		if err != nil {
			baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
			return
		}
	}

	viewCountMap, err := service.ServicePostInstance.GetViewCountByPostIDs(c, []uint64{uint64(postInfo.ID)})
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}

	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"post": model.PostMoreInfo{
			PostInfo:    postInfo,
			CommentNums: count,
		},
		"user": model.UserInfo{
			Uid:       userResponse.Uid,
			NickName:  userResponse.NickName,
			HeaderImg: userResponse.HeaderImg,
		},
		"camp_info":  campInfo,
		"view_count": viewCountMap[strconv.Itoa(int(postInfo.ID))],
	})
}

func PostRecord(c *gin.Context) {
	var request req.PostRecordReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	err := service.ServicePostInstance.PostRecord(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func PostLike(c *gin.Context) {
	var request req.PostLikeOrNotReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	row, err := service.ServicePostInstance.PostLikeOrNot(c, request, true)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", row)
}

func PostUnLike(c *gin.Context) {
	var request req.PostLikeOrNotReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	row, err := service.ServicePostInstance.PostLikeOrNot(c, request, false)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", row)
}

func FollowList(c *gin.Context) {
	var request req.CursorInfo
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, cursor, hasMore, err := service.ServicePostInstance.GetFollowList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"cursor":   cursor,
		"has_more": hasMore,
	})
}

func RecommendList(c *gin.Context) {
	var request req.RecommendListReq
	if err := c.ShouldBindQuery(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, cursor, hasMore, err := service.ServicePostInstance.GetRecommendList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"cursor":   cursor,
		"has_more": hasMore,
	})
}

func NearByList(c *gin.Context) {
	var request req.NearByListReq
	if err := c.ShouldBindQuery(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, cursor, hasMore, err := service.ServicePostInstance.NearByList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"cursor":   cursor,
		"has_more": hasMore,
	})
}

func PunchList(c *gin.Context) {
	var request req.PunchListReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, cursor, hasMore, count, err := service.ServicePostInstance.PunchList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"cursor":   cursor,
		"count":    count,
		"has_more": hasMore,
	})
}

func PunchRecommendList(c *gin.Context) {
	var request req.PunchListReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, _, _, _, err := service.ServicePostInstance.PunchList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list": list,
	})
}

func CreateSubject(c *gin.Context) {
	var request req.SubjectCreateReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	result, tmperr := json.Marshal(request.ReqImages)
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}
	request.Pictures = string(result)

	err := service.ServicePostInstance.SubjectCreate(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func UpdateSubject(c *gin.Context) {
	var target map[string]interface{}
	if err := c.ShouldBindBodyWith(&target, binding.JSON); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	result, tmperr := json.Marshal(target["req_images"])
	if tmperr != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, tmperr.Error(), nil)
		return
	}
	target["pictures"] = string(result)

	var request req.SubjectUpdateReq
	elem := reflect.TypeOf(&request).Elem() //通过反射获取type定义
	for i := 0; i < elem.NumField(); i++ {
		if elem.Field(i).Tag.Get("gorm") == "-" && len(elem.Field(i).Tag.Get("json")) > 0 {
			delete(target, elem.Field(i).Tag.Get("json"))
		}
	}

	err := service.ServicePostInstance.SubjectUpdateForMap(target)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func DeleteSubjectList(c *gin.Context) {
	var request req.IdsReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	err := service.ServicePostInstance.DeleteSubjectList(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", nil)
}

func GetSubjectList(c *gin.Context) {
	var request req.SubjectListReq
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, total, err := service.ServicePostInstance.GetSubjectList(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list":     list,
		"total":    total,
		"page":     request.Page,
		"pageSize": request.PageSize,
	})
}

func SubjectList(c *gin.Context) {
	list, err := service.ServicePostInstance.SubjectList()
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list": list,
	})
}

func SubjectPostCreate(c *gin.Context) {
	var request model.SubjectPost
	if err := c.ShouldBindJSON(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}

	err := service.ServicePostInstance.SubjectPostCreate(request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}

	baseHttp.WriteResponse(c, 0, "success", nil)
}

func SubjectContentList(c *gin.Context) {
	var request req.SubjectContentListReq
	if err := c.ShouldBindQuery(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, hasMore, err := service.ServicePostInstance.SubjectContentList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"has_more": hasMore,
		"list":     list,
	})
}

func TopicSearch(c *gin.Context) {
	var request req.TopicSearchReq
	if err := c.ShouldBindQuery(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	list, err := service.ServicePostInstance.TopicSearchList(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", gin.H{
		"list": list,
	})
}

func TopicDetail(c *gin.Context) {
	var request req.TopicDetailReq
	if err := c.ShouldBindQuery(&request); err != nil {
		baseHttp.WriteResponse(c, http.StatusBadRequest, err.Error(), nil)
		return
	}
	data, err := service.ServicePostInstance.TopicDetail(c, request)
	if err != nil {
		baseHttp.WriteResponse(c, http.StatusInternalServerError, err.Error(), nil)
		return
	}
	baseHttp.WriteResponse(c, 0, "success", data)
}
